import PixelMap from "@ohos.multimedia.image"
import { map } from "@kit.ConnectivityKit"
import { promptAction } from "@kit.ArkUI"

export interface linkLine {
  sid: number
  eid: number
  // // sp:number[]
  // // ep:number[]
  // toString(){
  //   return " sid "+this.sid+" eid "+this.eid
  //     // +" sp" +this.sp+" ep "+this.ep
  // }
  // constructor(sid:number,eid:number){
  //   this.sid=sid
  //   this.eid=eid
  //   // this.sp=sp
  //   // this.ep=ep
  //   console.log("_:_linkLine created:",this.toString())
  // }
}

export enum execStat {
  UNDEFINED,
  VISITED,
  ROOT,
  LINK
}

// @Observed
export interface node {
  // execFun: (input: multiIO) => Promise<multiIO>
  id: number
  name: string
  input: multiIO[]
  result: multiIO
  inputType: string
  outputType: string
  model: string
  prompt: string
  nodeType: number
  status: execStat
  p: number[]
  prev: number[]
  next: number[]
}

export interface rawNode {
  id: number,
  name: string,
  prompt: string,
  inputType: string,
  outputType: string,
  prev: number[],
  next: number[],
}

export function rawNodesConverter(rawnodes: rawNode[]): node[] {
  let errorNodeId = 6
  return rawnodes.map((rawnode) => {
    try {
      return {
        id: rawnode.id,
        input: [],
        result: dMultiIO(),
        name: rawnode.name,
        inputType: rawnode.inputType,
        outputType: rawnode.outputType,
        model: "",
        prompt: rawnode.prompt,
        nodeType: 1,
        status: execStat.UNDEFINED,
        p: [(rawnode.id % 2) * 250, (rawnode.id / 2) * 200],
        prev: rawnode.prev,
        next: rawnode.next,
      }
    } catch (e) {
      console.error("_:_rawNodesConverter " + JSON.stringify(e) + " error when processing" + JSON.stringify(rawnode))
      promptAction.showToast({
        message: "_:_rawNodesConverter " + JSON.stringify(e) + " error when processing\n" + JSON.stringify(rawnode)
      })
      return defaultNode(errorNodeId++)
    }
  })

}

export type nodeT = string | number | number[] | node[] | execStat | ((input: multiIO) => Promise<multiIO>)
  | undefined

// export function DOreplacer(key: string, value: nodeT): nodeT {
//   switch (key) {
//     case "id":
//       return value?.toString().slice(-3)
//     case "name":
//     case "inputType":
//     case "outputType":
//     case "model":
//     case "prompt":
//       if (value != "") {
//         return value
//       }
//       return undefined
//     case "p":
//       return undefined
//     default:
//       return value
//   }
// }

export function defaultNode(id: number = 0): node {
  return {
    id: id,
    input: [],
    result: dMultiIO(),
    name: "",
    inputType: "text",
    outputType: "text",
    model: "",
    prompt: "",
    nodeType: 1,
    status: execStat.UNDEFINED,
    p: [0, 0],
    next: [],
    prev: [],
  }
}

export interface multiIO {
  text: string,
  JSON: string,
  code: string,
  pix: PixelMap.PixelMap | undefined,
  imgPath: string,
  audioPath: string,
  vec: string,
  rdbName: string,
  rdbTableName: string,
  kvdbName: string,
  kvdbKey: string
}

export type multiIOT = string | PixelMap.PixelMap | undefined

export function replacer(key: string, value: multiIOT | nodeT): multiIOT | nodeT {
  switch (key) {
    case "id":
      return value?.toString().slice(-3)
    case "p":
      return undefined
    case "name":
    case "inputType":
    case "outputType":
    case "model":
    case "prompt":

    case "JSON":
    case "code":
    case "imgPath":
    case "audioPath":
    case "vec":
    case "rdbName":
    case "rdbTableName":
    case "kvdbName":
    case "kvdbKey":
      if (value != "") {
        return value
      }
      return undefined
    default:
      return value
  }
}

export function dMultiIO(text: string = ""): multiIO {
  return {
    text: text,
    JSON: "",
    code: "",
    pix: undefined,
    imgPath: "",
    audioPath: "",
    vec: "",
    rdbName: "",
    rdbTableName: "",
    kvdbName: "",
    kvdbKey: ""
  }
}

export interface nodeid {
  NodeId: number,
  workFlowName: string
}

export interface fromtoid {
  fromId: number,
  toId: number
}

export interface workFlow {
  nodes: node[],
  // linkLines: linkLine[],
  // focussKeys: number[]
}


export interface workFlowItem {
  name: string
}

export interface graphs2graph {
  workFlowName: string
}

export interface taskItem {
  name: string,
  steps: string,
  gparams: string,
  task: string,
  historycalls: string
}

export interface jtaskItem {
  name: string,
  steps: taskstep[],
  gparams: globparam[],
  task: string,
  historycalls: funcCall[],
}

export function defaultTaskItem(name: string, task: string): taskItem {
  return {
    name: name,
    steps: JSON.stringify([]),
    gparams: JSON.stringify([]),
    historycalls: JSON.stringify([]),
    task: task,
  }
}

export function defaultJTaskItem(name: string, task: string): jtaskItem {
  return {
    name: name,
    steps: [],
    gparams: [],
    historycalls: [],
    task: task,
  }
}

export function defaultTaskStep(name: string): taskstep {
  return {
    functionName: name,
    stepparams: [],
  }
}

export interface tasks2task {
  task_name: string
}

export interface taskstep {
  functionName: string,
  stepparams: stepparam[],
}

export function call2taskstep(call: funcCall): taskstep {
  let taskStep: taskstep = defaultTaskStep(call.functionName)
  call.gparams.forEach((gparam) => {
    taskStep.stepparams.push({ key: gparam.key, value: gparam.value, globalkey: "" })
  })
  return taskStep
}

// export interface historytaskstep {
//   functionName: string,
//   globparams: globparam[],
// }

export interface globparam {
  key: string,
  value: string
}

export interface stepparam {
  key: string,
  value: string,
  globalkey: string,
}

export interface funcCall {
  task: string,
  functionName: string,
  gparams: globparam[],
}

export function dfuncCall(task = "default", functionName = "default"): funcCall {
  return {
    task: task,
    functionName: functionName,
    gparams: []
  }
}

function trackReplacer(key, value) {
  // if (key == "call") {
  //   return funcCall4LLM(value)
  // }
  if (key == "LMpageDesc") {
    return value
  }
  if (key == "operMode") {
    return OperMode[value]
  }
}


export enum execModes {
  step,
  direct
}

export interface taskTrack {
  call: funcCall
  visited: string,
  operMode: string,
  LMpageDesc: string,
  pageDescH: string,
  imgPath: string,
}

export function dTrack(visited = "false", mode = "", LMpageDesc = "", pageDescH = "", imgPath = ""): taskTrack {
  return {
    call: {
      task: "",
      functionName: "",
      gparams: []
    },
    visited: visited,
    operMode: mode,
    LMpageDesc: LMpageDesc,
    pageDescH: pageDescH,
    imgPath: imgPath,
  }
}

export let buildinTaskFun: string[] = ["scrollclick", "type", "click", "scroll", "back", "backHome", "keyCode"]

export let NoDirectStepCallFun: string[] = ["scrollclick", "type", "click", "scroll"]

export enum OperMode {
  PlanStep,
  DOM,
  LLMtag,
  VLMtag,
  AUTO,
  back,
  completed,
  NotDefined,
  Manual
}

export interface navigate {
  nextOperMode: string
}

export interface LMreply {
  taskStatus: string,
  pageDesc: string,
  action: string,
  targetId: number,
  scrollDir: string,
  keyCode: number,
  inputText: string,
  targetText: string
}

export interface ExecResult {
  PageNotTurnWarn: number,
  ElemNotFoundError: number,
  LMstatus: string,
  success: boolean,
  replyParseError: boolean
}

export function dExecResult(LMstatus: string = ""): ExecResult {
  return {
    PageNotTurnWarn: -1,
    ElemNotFoundError: -1,
    LMstatus: LMstatus,
    success: true,
    replyParseError: false,
  }
}

// @Observed
// export class node {
//   id: number
//   p:number[]
//   links: node[]
//   focus: number = 0
//
//   constructor(id:number, p:number[]=[0,0], links = []) {
//     this.id = id
//     this.p=p
//     this.links = links
//     console.log("_:_node created:",id,p,links)
//   }
//
//   toString() {
//     return JSON.stringify({
//       id:this.id,
//       x: this.p[0],
//       y: this.p[1],
//       links: this.links.map(link => link.id),
//       focus: this.focus
//     })
//   }
// }

// let TAG = "_:_graph"
//
// export class graph {
//   relations: linkLine[]
//
//   constructor() {
//     this.relations = [];
//   }
//
//   // 添加关系，确保不重复
//   add(relation: linkLine) {
//     // 检查关系是否已经存在
//     const existingRelation = this.relations.find(r =>
//     r.sid === relation.sid && r.eid === relation.eid
//     );
//
//     if (!existingRelation) {
//       this.relations.push(relation);
//     } else {
//       console.error(TAG, 'Relation already exists');
//     }
//   }
//
//   // 根据sid或eid删除关系
//   delete(id: number) {
//     this.relations = this.relations.filter(relation =>
//     !(relation.sid === id || relation.eid === id)
//     );
//   }
//
//   // 获取所有关系
//   get() {
//     return this.relations;
//   }
// }